package com.quanyan.weichat.common;

import com.quanyan.common.utils.ObjectUtil;
import org.apache.http.Consts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

/**
 * User: rizenguo
 * Date: 2014/10/29
 * Time: 15:23
 */
public class Signature {

    private static  Logger logger = LoggerFactory.getLogger(Signature.class);
    /**
     * 签名算法
     *
     * @param o 要参与签名的数据对象
     * @return 签名
     * @throws IllegalAccessException
     */
    public static String getSign(Object o, String key) throws IllegalAccessException {
        String result = getDictString(o);
       // result += "key=" + Configure.getKey();
        result += "key=" + key;
        logger.debug("Sign Before MD5:" + result);
        result = MD5.MD5Encode(result).toUpperCase();
        logger.debug("Sign Result:" + result);
        return result;
    }

    private static String getDictString(Object o) throws IllegalAccessException {
        ArrayList<String> list = new ArrayList<String>();
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        if (fields == null || fields.length == 0) {
            fields = cls.getSuperclass().getDeclaredFields();
        }
        for (Field f : fields) {
            f.setAccessible(true);
            if (!StringUtils.isEmpty(f.get(o))) {
                list.add(f.getName() + "=" + f.get(o) + "&");
            }
        }
        int size = list.size();
        String[] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            sb.append(arrayToSort[i]);
        }
        return sb.toString();
    }

    public static String SHA1(Object o) {
        try {
            String dictString = getDictString(o);
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(dictString.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (Exception e) {
            logger.error(ObjectUtil.getFullStackTraceToString(e));
        }
        return "";
    }


    public static String SHA1(Map<String, String> map) {
        try {
            String dictString = mapToSignString(map);
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(dictString.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (Exception e) {
            logger.error(ObjectUtil.getFullStackTraceToString(e));
        }
        return "";
    }


    public static String getSign(Map<String, String> map, String key) {
        String result = mapToSignString(map);
        result += "key=" + key;
        logger.debug("Sign Before MD5:" + result);
        String sign = MD5.MD5Encode(result).toUpperCase();
        logger.debug("Sign Result:" + sign);
        return sign;
    }

    private static String mapToSignString(Map<String, String> map) {
        ArrayList<String> list = new ArrayList<String>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            if (!StringUtils.isEmpty(entry.getValue())) {
                list.add(new String(entry.getKey().getBytes(), Consts.UTF_8) + "=" + new String(entry.getValue().toString().getBytes(), Consts.UTF_8) + "&");
            }
        }
        int size = list.size();
        String[] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            sb.append(arrayToSort[i]);
        }
        String result = sb.toString();
        logger.debug("Map 2 String ==> " + result);
        return result;

    }

    /**
     * 校验签名是否正确
     * @param map
     * @return
     */
    public static boolean isValidSign(Map<String, String> map, String key) {
        String sign = map.remove("sign");
        String check = getSign(map,key);
        logger.debug("sign = " + sign + ", check = " + check);
        map.put("sign",sign);
        return sign.equals(check);
    }

}
